#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include "../support/Threading.hpp"

#include "SWARMTask.hpp"
#include "SWARMTaskTag.hpp"
#include "SWARMTaskTagWrapper.hpp"
#include "Externs.hpp"

#include <swarm/type_setup.h>
#include <swarm/Locale.h>
#include <swarm/Latch.h>
#include <swarm/Bool.h>
#include <swarm/Runtime.h>
#include <swarm/Resource.h>
#include <swarm/Scheduler.h>
#include <swarm/Env.h>
#include <swarm/Identifiable.h>
#include <swarm/util/atomic.h>
// #include <swarm/Nat64.h>
#include <swarm/TagTable.h>
#include <eti/tracing.h>
#include <eti/swarm_convenience.h>


swarm_CodeletDesc_IMPL_NOCANCEL_NOCAST(startup, startup, swarm_c_void, swarm_c_void)
const SwarmTagWrapper<SwarmTaskTag<0, 7, 3>> *tag_wrapper = 
  SwarmTagWrapper<SwarmTaskTag<0, 7, 3> >::
  _cast_fromAny((swarm_Any_i *)(void *)THIS);
const SwarmTaskTag<0, 7, 3> &tag = *(tag_wrapper->tInst);

int64_t pT = tag[0+3];
int64_t pM = tag[1+3];
int64_t pN = tag[2+3];
int64_t pP = tag[3+3];
    
// Init tag table related to problem size 
swarm_TagTable_init(&polySwarmTaskTags, 1023);  
std::cerr << "Starting Spawn " << pT << " " << pN << " " << pM << " " 
<< pT << "\n";

{ // Auto-generated polyhedral loops
  int64_t t1, t2, t3;
  for (t1=ceild(-pN-15,16);t1<=floord(pT-3,16);t1++) {
    for (t2=max(t1,-t1-1);
	 t2<=min(min(floord(-8*t1+pT-2,8),floord(8*t1+pN+7,8)),floord(pT+pN-2,16));t2++) {
      for (t3=max(max(0,ceild(t1+t2-1,2)),ceild(16*t2-pN-14,16));
	   t3<=min(min(floord(pT+pN-2,16),floord(16*t2+pN+14,16)),floord(8*t1+8*t2+pN+15,16));
	   t3++) {
        
	SwarmTaskTag<0, 7, 3> *t = new SwarmTaskTag<0, 7, 3> 
	  (static_cast<tag_elem_t>(t1),  static_cast<tag_elem_t>(t2),  
	   static_cast<tag_elem_t>(t3),  static_cast<tag_elem_t>(pT),  
	   static_cast<tag_elem_t>(pM),  static_cast<tag_elem_t>(pN),  
	   static_cast<tag_elem_t>(pP));

        SwarmTagWrapper<SwarmTaskTag<0, 7, 3> > *stw = 
          new SwarmTagWrapper<SwarmTaskTag<0, 7, 3> > (t);

	// Spawn codelet corresponding to t.
#ifdef DEBUG
	SEQUENTIAL_DUMP1("Spawn " << *t << "\n");
#endif
        global_count++;
	swarm_schedule(&swarm_CodeletDesc_CODELET(heat3d), stw, NULL, NULL, NULL);
	// swarm_dispatch(&swarm_CodeletDesc_CODELET(heat3d), stw, NULL, NULL, NULL);
      }
    }
  }
}
// swarm_dispatch(NEXT, NEXT_THIS, NULL, NULL, NULL);
swarm_CodeletDesc_IMPL_END;
